package experiment1;

import java.util.Random;

class Particle {
    double[] position; // 粒子的位置
    double[] velocity; // 粒子的速度
    double[] bestPosition; // 粒子的历史最佳位置
    double bestFitness; // 粒子的历史最佳适应度

    Particle(int n) {
        position = new double[n];
        velocity = new double[n];
        bestPosition = new double[n];
        bestFitness = Double.MAX_VALUE;
    }

    // 初始化粒子位置和速度
    void initialize(double minValue, double maxValue) {
        Random rand = new Random();
        for (int i = 0; i < position.length; i++) {
            position[i] = minValue + (maxValue - minValue) * rand.nextDouble();
            velocity[i] = (maxValue - minValue) * rand.nextDouble() / 2;
            bestPosition[i] = position[i];
        }
        bestFitness = fitness(position);
    }

    // 计算适应度（Griewank函数）
    double fitness(double[] x) {
        double sum = 0;
        double product = 1;
        for (int i = 0; i < x.length; i++) {
            sum += x[i] * x[i];
            product *= Math.cos(x[i] / Math.sqrt(i + 1));
        }
        return 1 + sum / 4000 - product;
    }
}

class PSO {
    Particle[] particles;
    double[] globalBestPosition;
    double globalBestFitness;
    int dimension;
    double minValue = -600;
    double maxValue = 600;
    int swarmSize = 30;
    int maxIter = 1000;
    double w = 0.5; // 惯性权重
    double c1 = 1.5; // 个体学习因子
    double c2 = 1.5; // 社会学习因子

    PSO(int dimension) {
        this.dimension = dimension;
        particles = new Particle[swarmSize];
        globalBestPosition = new double[dimension];
        globalBestFitness = Double.MAX_VALUE;
    }

    // 初始化粒子群
    void initialize() {
        for (int i = 0; i < swarmSize; i++) {
            particles[i] = new Particle(dimension);
            particles[i].initialize(minValue, maxValue);
            if (particles[i].bestFitness < globalBestFitness) {
                globalBestFitness = particles[i].bestFitness;
                globalBestPosition = particles[i].bestPosition.clone();
            }
        }
    }

    // 更新粒子群
    void updateParticles() {
        Random rand = new Random();
        for (int i = 0; i < swarmSize; i++) {
            Particle p = particles[i];
            for (int j = 0; j < dimension; j++) {
                // 更新速度
                p.velocity[j] = w * p.velocity[j] + c1 * rand.nextDouble() * (p.bestPosition[j] - p.position[j])
                        + c2 * rand.nextDouble() * (globalBestPosition[j] - p.position[j]);

                // 更新位置
                p.position[j] += p.velocity[j];
            }

            // 计算适应度
            double fitness = p.fitness(p.position);
            if (fitness < p.bestFitness) {
                p.bestFitness = fitness;
                p.bestPosition = p.position.clone();
            }

            if (fitness < globalBestFitness) {
                globalBestFitness = fitness;
                globalBestPosition = p.position.clone();
            }
        }
    }

    // 粒子群优化
    void optimize() {
        initialize();
        for (int iter = 0; iter < maxIter; iter++) {
            updateParticles();
            if (iter % 10 == 0) {
                System.out.println("第 " + iter + " 次迭代： 当前最佳适应度 = " + globalBestFitness);
            }
        }
    }

    // 获取最优解
    double[] getGlobalBestPosition() {
        return globalBestPosition;
    }
}

public class GriewankFuncPSO {
    public static void main(String[] args) {
        int dimension = 2; // n = 2
        PSO pso = new PSO(dimension);
        pso.optimize();

        System.out.println("优化结束。");
        System.out.println("全局最佳位置： ");
        for (int i = 0; i < dimension; i++) {
            System.out.print(pso.getGlobalBestPosition()[i] + " ");
        }
        System.out.println();
        System.out.println("全局最佳适应度: " + pso.globalBestFitness);
    }
}

